package org.zpmis.common.base;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.zpmis.common.constant.UserConstants;
import org.zpmis.common.exception.BusinessException;
import org.zpmis.common.result.ResultCode;
import org.zpmis.common.utils.RedisUtil;
import org.zpmis.common.utils.StringUtil;
import org.zpmis.common.utils.json.GsonUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 项目抽象BaseWebService
 */
@Slf4j
public abstract class BaseWebService {

    @Resource
    protected RedisUtil redisUtil;

    protected HttpServletRequest getRequest(){
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.getRequestAttributes())).getRequest();
        return request;
    }

    protected HttpServletResponse getResponse(){
        HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.getRequestAttributes())).getResponse();
        return response;
    }
    /**
     * 从请求头中获取token
     *
     * @return
     */
    protected String getTokenFromHeader() {
        return getRequest().getHeader("Authorization");
    }

    /**
     * 获取当前登录小程序用户JSON
     * @return
     */
    protected AppletsLoginUser getAppletsLoginUser(){
        //AppletsLoginUser appletsLoginUser = (AppletsLoginUser)redisUtil.get(String.format(UserConstants.USER_TOKEN_REDIS_KEY, getTokenFromHeader()));
        String tokenFromHeader = getTokenFromHeader();
        if(StringUtil.isEmpty(tokenFromHeader)){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Object o = redisUtil.get(String.format(UserConstants.APPLETS_USER_TOKEN_REDIS_KEY, tokenFromHeader));
        if(o == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Object parse = JSON.parse(o.toString());
        AppletsLoginUser appletsLoginUser = JSONObject.parseObject(JSONObject.toJSONString(parse),AppletsLoginUser.class);
        if(!"1".equals(appletsLoginUser.getLoginType())){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        return appletsLoginUser;
    }

    /**
     * 获取当前登录admin用户JSON
     * @return
     */
    protected AdminLoginUser getAdminLoginUser(){
        //AppletsLoginUser appletsLoginUser = (AppletsLoginUser)redisUtil.get(String.format(UserConstants.USER_TOKEN_REDIS_KEY, getTokenFromHeader()));
        String tokenFromHeader = getTokenFromHeader();
        if(StringUtil.isEmpty(tokenFromHeader)){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Object o = redisUtil.get(String.format(UserConstants.ADMIN_USER_TOKEN_REDIS_KEY, tokenFromHeader));

        if(o == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Object parse = JSON.parse(o.toString());
        AdminLoginUser adminLoginUser = JSONObject.parseObject(JSONObject.toJSONString(parse),AdminLoginUser.class);

        if(!"2".equals(adminLoginUser.getLoginType())){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        return adminLoginUser;
    }

    /**
     * 获取请求的ip地址
     *
     * @return
     */
    protected final String getIpAddr() {
        String ip = getRequest().getHeader("x-forwarded-for");
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = getRequest().getHeader("Proxy-Client-IP");
        }

        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = getRequest().getHeader("WL-Proxy-Client-IP");
        }

        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = getRequest().getRemoteAddr();
        }

        return ip;
    }

    /**
     * 根据用户id使用户登录失效
     * @param userIds
     */
    protected void userIdLogout(List<Long> userIds){

        //根据用户id 退出对应的用户
        List<String> tokenRedisKeys = userIds.stream().map(userId -> {
            String format = String.format(UserConstants.ADMIN_USER_INFO_REDIS_KEY, userId);
            return format;
        }).collect(Collectors.toList());
        //通过存储tokenKey 查询出该角色下的所有用户token
        List<String> infoRedisKeys = tokenRedisKeys.stream().filter(key -> redisUtil.get(key) != null).map(redisKey -> {
            Object o = redisUtil.get(redisKey);
            return String.format(UserConstants.ADMIN_USER_TOKEN_REDIS_KEY, o.toString());
        }).collect(Collectors.toList());

        List<String> detailRedisKeys = userIds.stream().map(userId -> {
            String format = String.format(UserConstants.ADMIN_USER_LOGIN_DETAIL_KEY, userId);
            return format;
        }).collect(Collectors.toList());
        //删除用户存储的tokenKey 和 登录信息的key 促使登录失效
        redisUtil.delKeys(tokenRedisKeys);
        redisUtil.delKeys(infoRedisKeys);
        redisUtil.delKeys(detailRedisKeys);
    }

    /**
     * 删除用户的菜单权限缓存
     */
    protected void delLoginUserRedisDetail(){
        Set<String> keys = redisUtil.getByPattern(String.format(UserConstants.ADMIN_USER_LOGIN_DETAIL_KEY, "*"));
        if(keys != null && !keys.isEmpty()){
            redisUtil.delKeys(keys);
        }
    }

    /**
     *  对象属性去重函数自定义lambda
     * @param keyExtractor
     * @param <T>
     * @return
     */
    protected static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return object -> seen.putIfAbsent(keyExtractor.apply(object), Boolean.TRUE) == null;
    }
}
